package edison.jcr;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Calendar;

import javax.jcr.Binary;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;

public class ValueImpl implements Value {

	private final String value;
	private final int type;

	ValueImpl(String value, int type) {
		this.value = value;
		this.type = type;
	}

	public String getString() throws ValueFormatException, IllegalStateException, RepositoryException {
		if (type == PropertyType.BINARY)
			throw new ValueFormatException();
		return value;
	}

	public InputStream getStream() throws RepositoryException {
		if (type != PropertyType.BINARY)
			throw new ValueFormatException();
		return new ByteArrayInputStream(value.getBytes());
	}

	public Binary getBinary() throws RepositoryException {
		if (type != PropertyType.BINARY)
			throw new ValueFormatException();
		return new BinaryImpl(value.getBytes());
	}

	public long getLong() throws ValueFormatException, RepositoryException {
		if (type == PropertyType.BINARY)
			throw new ValueFormatException();

		try {
			return Long.parseLong(value, Character.MAX_RADIX);
		} catch (NumberFormatException e) {
			throw new ValueFormatException(e);
		}
	}

	public double getDouble() throws ValueFormatException, RepositoryException {
		if (type == PropertyType.BINARY)
			throw new ValueFormatException();

		try {
			return Double.parseDouble(value);
		} catch (NumberFormatException e) {
			throw new ValueFormatException(e);
		}

	}

	public BigDecimal getDecimal() throws ValueFormatException, RepositoryException {
		if (type == PropertyType.BINARY)
			throw new ValueFormatException();

		try {
			return new BigDecimal(value);
		} catch (NumberFormatException e) {
			throw new ValueFormatException(e);
		}
	}

	public Calendar getDate() throws ValueFormatException, RepositoryException {
		if (type == PropertyType.BINARY)
			throw new ValueFormatException();

		try {
			Calendar calendar = Calendar.getInstance();
			long millis = Long.parseLong(value, Character.MAX_RADIX);
			calendar.setTimeInMillis(millis);
			return calendar;
		} catch (NumberFormatException e) {
			throw new ValueFormatException(e);
		}
	}

	public boolean getBoolean() throws ValueFormatException, RepositoryException {
		if (type != PropertyType.BOOLEAN)
			throw new ValueFormatException();
		return Boolean.parseBoolean(value);
	}

	public int getType() {
		return type;
	}

	@Override
	public int hashCode() {
		return value.hashCode() + type;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof Value) {
			Value v2 = (Value) obj;
			if (this.toString().equals(v2.toString()) && this.getType() == v2.getType()) {
				return true;
			}
		}

		return false;
	}

	@Override
	public String toString() {
		return value;
	}

}